package org.dtrd.modules.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dtrd.common.system.vo.LoginUser;
import org.dtrd.config.system.Constant;
import org.dtrd.modules.archive.entity.po.DtrdEntRdArchiveReverseScheme;
import org.dtrd.modules.archive.service.IDtrdEntRdArchiveReverseSchemeService;
import org.dtrd.modules.doctor.entity.bean.DoctorTeam;
import org.dtrd.modules.doctor.entity.bean.TeamDoctorInfo;
import org.dtrd.modules.doctor.service.IDtrdRlDoctorPatientService;
import org.dtrd.modules.doctor.service.IDtrdRlDoctorTeamDoctorService;
import org.dtrd.modules.patient.entity.po.DtrdEntRdPatient;
import org.dtrd.modules.patient.service.IDtrdEntRdPatientService;
import org.dtrd.modules.service.entity.bean.*;
import org.dtrd.modules.service.entity.po.*;
import org.dtrd.modules.service.mapper.DtrdEntRdServicePackageMapper;
import org.dtrd.modules.service.service.*;
import org.dtrd.modules.util.ShiroUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务包信息 服务实现类
 * </p>
 *
 * @author QR
 * @since 2021-11-19 18:52:54
 */
@DS("multi-datasource1")
@Service
@Slf4j
public class DtrdEntRdServicePackageServiceImpl extends ServiceImpl<DtrdEntRdServicePackageMapper, DtrdEntRdServicePackage> implements IDtrdEntRdServicePackageService {

    @Autowired
    private IDtrdRlServicePackageService servicePackageRlService;
    @Autowired
    private IDtrdRlPackagePatientService packagePatientRlService;
    @Autowired
    private IDtrdEntRdServiceService serviceService;
    @Autowired
    private IDtrdRlPatientServiceDetailService patientServiceDetailService;
    @Autowired
    private IDtrdEntRdPatientService patientService;
    @Autowired
    private IDtrdRlDoctorPatientService doctorPatientRlService;
    @Autowired
    private IDtrdRlDoctorTeamDoctorService doctorTeamRlService;
    @Autowired
    private IDtrdEntRdServicePackageSpecsService servicePackageSpecsService;
    @Autowired
    private IDtrdEntRdArchiveReverseSchemeService reverseSchemeService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeServicePackage(Integer packageId) {
        // 删除服务包表数据
        boolean packageResult = removeById(packageId);
        // 删除服务包和服务套餐关系表数据
        LambdaQueryWrapper<DtrdRlServicePackage> queryWrapper = Wrappers.lambdaQuery(DtrdRlServicePackage.class)
                .eq(DtrdRlServicePackage::getPackageId, packageId);
        servicePackageRlService.remove(queryWrapper);
        return packageResult;
    }

    @Override
    public List<ServiceDetailItem> getThreeUnFinishedServiceDetailLatest(Integer patientId) {
        DtrdRlPackagePatient servicingPackage = packagePatientRlService.getServicingPatientPackage(patientId);
        List<ServiceDetailItem> serviceDetailItems = null;
        // 获取服务中状态的服务包，查询最新的三条未完成状态的服务项
        if (servicingPackage != null) {
            Integer packageId = servicingPackage.getPackageId();
            LambdaQueryWrapper<DtrdRlPatientServiceDetail> wrapper = Wrappers.lambdaQuery(DtrdRlPatientServiceDetail.class)
                    .eq(DtrdRlPatientServiceDetail::getPatientId, patientId)
                    .eq(DtrdRlPatientServiceDetail::getPackageId, packageId)
                    .eq(DtrdRlPatientServiceDetail::getStatus, Constant.ServiceItemStatus.NOT_DONE.getType())
                    .orderByAsc(DtrdRlPatientServiceDetail::getPeriod)
                    .last("limit 3");
            List<DtrdRlPatientServiceDetail> serviceDetails = patientServiceDetailService.list(wrapper);
            if (CollectionUtil.isNotEmpty(serviceDetails)) {
                serviceDetailItems = serviceDetails.stream()
                        .map(s -> {
                            ServiceDetailItem item = new ServiceDetailItem().parseFromPO(s);
                            Integer serviceId = item.getServiceId();
                            item.setServiceName(serviceService.getServiceName(serviceId));
                            return item;
                        })
                        .collect(Collectors.toList());
            }
        }
        return serviceDetailItems;
    }

    @Override
    public boolean hasSamePackageName(Integer packageId, String packageName, String orgCode) {
        LambdaQueryWrapper<DtrdEntRdServicePackage> wrapper = Wrappers.lambdaQuery(DtrdEntRdServicePackage.class)
                .eq(DtrdEntRdServicePackage::getPackageName, packageName)
                .eq(DtrdEntRdServicePackage::getOrgCode, orgCode);
        DtrdEntRdServicePackage queryPackage = getOne(wrapper);
        return queryPackage != null && !Objects.equals(packageId, queryPackage.getDataId());
    }

    @Override
    public PatientServiceRelationInfo getPatientServiceRelationInfo(Integer patientId, Integer relationId) {
        PatientServiceRelationInfo info = new PatientServiceRelationInfo();
        // 服务包信息
        DtrdRlPackagePatient packagePatient = packagePatientRlService.getById(relationId);
        DtrdEntRdServicePackage servicePackage = getById(packagePatient.getPackageId());
        if (servicePackage == null) {
            return null;
        }
        info.parseFromPO(servicePackage);
        // 患者信息
        DtrdEntRdPatient patient = patientService.getById(patientId);
        info.parseFromPO(patient);
        // 获取患者关联的 doctorId
        Integer doctorId = doctorPatientRlService.getDoctorIdByPatientId(patientId);
        if (doctorId != null) {
            DoctorTeam doctors = doctorTeamRlService.getTeamDoctors(doctorId);
            List<TeamDoctorInfo> teamDoctors = doctors.getTeamDoctors();
            info.setDoctorName(doctors.getManager().getDoctorName());
            for (TeamDoctorInfo teamDoctor : teamDoctors) {
                Constant.Executor type = Constant.Executor.valueOf(teamDoctor.getDoctorType());
                switch (type) {
                    case HEALTH_MANAGER:
                        info.setHealthManager(teamDoctor.getDoctorName());
                        break;
                    case PSYCHOLOGICAL_COUNSELOR:
                        info.setPsychologicalCounselor(teamDoctor.getDoctorName());
                        break;
                    case SPORT_THERAPIST:
                        info.setSportManager(teamDoctor.getDoctorName());
                        break;
                    case NUTRITION_MANAGER:
                        info.setDietician(teamDoctor.getDoctorName());
                        break;
                    default:
                        break;
                }
            }
        }
        info.parseFromPO(packagePatient);
        // 补充逆转方案中 知情同意书与服务协议  肖 2022-08-02 18:20:00
        DtrdEntRdArchiveReverseScheme reverseScheme = reverseSchemeService.getRecordByRelationId(relationId);
        info.parseFromPO(reverseScheme);
        return info;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdateServicePackage(ServicePackageInfo servicePackageInfo, String orgCode) {
        DtrdEntRdServicePackage servicePackage = new DtrdEntRdServicePackage();
        Integer dataId = servicePackageInfo.getDataId();
        if (dataId == null) {
            servicePackage.init();
        } else {
            // 如果修改服务包的内容时修改的周期 < 原来的周期 或 修改了服务包的类型, 将原来服务包的关系清空
            Integer type = servicePackageInfo.getPackageType();
            Integer period = servicePackageInfo.getPackageServicePeriod();

            checkPackageTypeAndPeriod(dataId, type, period);
        }
        servicePackage.parseFromDto(servicePackageInfo);
        // 设置操作者的 orgCode
        servicePackage.setOrgCode(orgCode);
        return saveOrUpdate(servicePackage);
    }

    private void checkPackageTypeAndPeriod(Integer packageId, Integer type, Integer period) {
        DtrdEntRdServicePackage queryPackage = getById(packageId);
        if (queryPackage == null) {
            return;
        }
        if (!Objects.equals(queryPackage.getPackageType(), type)
                || queryPackage.getPackageServicePeriod() > period) {
            servicePackageRlService.clearPackageRelation(packageId);
        }
    }

    @Override
    public String getPackageName(Integer packageId) {
        DtrdEntRdServicePackage servicePackage = getById(packageId);
        return Optional.ofNullable(servicePackage)
                .map(DtrdEntRdServicePackage::getPackageName)
                .orElse("");
    }

    @Override
    public String getServingPackageName(Integer patientId) {
        DtrdRlPackagePatient patientPackage = packagePatientRlService.getServicingPatientPackage(patientId);
        if (patientPackage != null) {
            return getPackageName(patientPackage.getPackageId());
        }
        return null;
    }

    @Override
    public List<ServicePackageInfo> getServicePackageList() {
        LoginUser loginUser = ShiroUtil.getLoginUser();
        LambdaQueryWrapper<DtrdEntRdServicePackage> queryWrapper = baseQueryWrapper();
        if (loginUser != null) {
            queryWrapper.eq(DtrdEntRdServicePackage::getOrgCode, loginUser.getOrgCode());
        }
        List<DtrdEntRdServicePackage> poList = list(queryWrapper);
        List<ServicePackageInfo> dtoList = new ArrayList<>(poList.size());
        if (CollectionUtil.isNotEmpty(poList)) {
            dtoList = poList.stream()
                    .map(po -> new ServicePackageInfo().parseFromPo(po)).collect(Collectors.toList());
        }
        return dtoList;
    }

    @Override
    public List<ServicePackageInfo> getServicePackageList(String orgCode) {
        LambdaQueryWrapper<DtrdEntRdServicePackage> queryWrapper = baseQueryWrapper()
                .eq(StringUtils.isNotBlank(orgCode),
                        DtrdEntRdServicePackage::getOrgCode, orgCode);
        List<DtrdEntRdServicePackage> poList = list(queryWrapper);
        List<ServicePackageInfo> dtoList = new ArrayList<>(poList.size());
        if (CollectionUtil.isNotEmpty(poList)) {
            dtoList = poList.stream()
                    .map(po -> new ServicePackageInfo().parseFromPo(po)).collect(Collectors.toList());
        }
        return dtoList;
    }

    @Override
    public ServicePackage getServicePackage(Integer packageId) {
        DtrdEntRdServicePackage servicePackage = getById(packageId);
        ServicePackage servicePackageInfo = Optional.ofNullable(servicePackage).map(ServicePackage::new).orElse(null);
        if (servicePackageInfo != null) {
            ServicePackage sp = servicePackageSpecsService.getServicePackageSpecsInfo(packageId, servicePackage.getPackageDiscount());
            if (sp != null) {
                servicePackageInfo.setSaleState(sp.getSaleState());
                servicePackageInfo.setPackageSpecs(sp.getPackageSpecs());
            }
        }
        return servicePackageInfo;
    }

    @Override
    public void clearPackage(Integer packageId) {
        LambdaUpdateWrapper<DtrdRlServicePackage> wrapper = Wrappers.lambdaUpdate(DtrdRlServicePackage.class)
                .eq(DtrdRlServicePackage::getPackageId, packageId);
        servicePackageRlService.remove(wrapper);
    }

    @Override
    public boolean isValidPackageId(Integer packageId) {
        DtrdEntRdServicePackage servicePackage = getById(packageId);
        return Optional.ofNullable(servicePackage).isPresent();
    }

    private LambdaQueryWrapper<DtrdEntRdServicePackage> baseQueryWrapper() {
        return Wrappers.lambdaQuery(DtrdEntRdServicePackage.class)
                .eq(DtrdEntRdServicePackage::getIsDel, 0);
    }

}
